package org.light.simpleauth;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.exception.ValidateException;
import org.light.generator.Generator;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;
import org.light.verb.FindById;

public class ExtractorsGenerator extends Generator{
	protected Domain userDomain;
	
	public ExtractorsGenerator(){
		super();
		super.fileName = "extractors.rs";
		super.standardName = "Extractors";
	}

	@Override
	public StatementList generateStatementList() throws ValidateException{
		List<Writeable> sList = new ArrayList<Writeable>();
		sList.add(new Statement(1000L,0,"use axum::{"));
		sList.add(new Statement(2000L,1,"async_trait,"));
		sList.add(new Statement(3000L,1,"extract::{Extension, FromRequest, TypedHeader},"));
		sList.add(new Statement(4000L,0,"};"));
		sList.add(new Statement(5000L,0,"use http::request::Parts;"));
		sList.add(new Statement(6000L,0,"use headers::{authorization::Bearer, Authorization};"));
		sList.add(new Statement(7000L,0,"use "+this.userDomain.getProjectName()+"::{"));
		sList.add(new Statement(8000L,1,this.userDomain.getDomainSuffix()+"::error::{ApiError, Error},"));
		sList.add(new Statement(9000L,1,this.userDomain.getDomainSuffix()+"::"+this.userDomain.getSnakeDomainNameWithSuffix()+"::"+this.userDomain.getCapFirstDomainNameWithSuffix()+","));
		sList.add(new Statement(10000L,0,"};"));
		sList.add(new Statement(11000L,0,"use crate::{"));
		sList.add(new Statement(12000L,1,"utils::jwt_util,"));
		sList.add(new Statement(13000L,0,"};"));
		sList.add(new Statement(14000L,0,""));
		FindById find = new FindById(this.userDomain);
		sList.add(new Statement(15000L,0,"use crate::"+this.userDomain.getServiceimplSuffix()+"::"+this.userDomain.getSnakeDomainName()+"_service::"+StringUtil.getSnakeName(find.getVerbName())+";"));
		sList.add(new Statement(16000L,0,""));
		sList.add(new Statement(17000L,0,"#[async_trait]"));
		sList.add(new Statement(18000L,0,"impl<S, B> FromRequest<S, B> for "+this.userDomain.getCapFirstDomainNameWithSuffix()));
		sList.add(new Statement(19000L,0,"where"));
		sList.add(new Statement(20000L,0,"B: Send + 'static,"));
		sList.add(new Statement(21000L,0,"S: Send + Sync,"));
		sList.add(new Statement(22000L,0,"{"));
		sList.add(new Statement(23000L,1,"type Rejection = ApiError;"));
		sList.add(new Statement(24000L,0,""));
		sList.add(new Statement(25000L,1,"async fn from_request(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {"));
		sList.add(new Statement(26000L,2,"let TypedHeader(Authorization(bearer)) ="));
		sList.add(new Statement(27000L,3,"TypedHeader::<Authorization<Bearer>>::from_request(req)"));
		sList.add(new Statement(28000L,4,".await"));
		sList.add(new Statement(29000L,4,".map_err(|err| Error::from(err))?;"));
		sList.add(new Statement(33000L,2,"let claims = jwt_util::verify(bearer.token())?;"));
		sList.add(new Statement(35000L,2,"Ok("+StringUtil.getSnakeName(find.getVerbName())+"(claims.sub).await?)"));
		sList.add(new Statement(36000L,1,"}"));
		sList.add(new Statement(37000L,0,"}"));

		return WriteableUtil.merge(sList);		
	}

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
	}

}
